/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.springBoot.springBootSysCore.common.persistence;

import java.util.Date;

import javax.persistence.*;

import com.alibaba.fastjson.annotation.JSONField;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.Until;
import com.springBoot.springBootSysCore.modules.enums.base.DeleteStateEnum;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.*;
import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.springBoot.springBootSysCore.common.comment.annotation.MyComment;
import com.springBoot.springBootSysCore.common.utils.IdGen;
import com.springBoot.springBootSysCore.modules.entity.system.SysUser;
import com.springBoot.springBootSysCore.modules.entity.utils.UserUtils;

/**
 * 数据Entity类
 * @author ThinkGem
 * @version 2014-05-16
 */
@MappedSuperclass
public abstract class DataEntity<T> extends BaseEntity<T> {
	private static final long serialVersionUID = 1L;
	protected String remarks;	// 备注
	protected SysUser createBy;	// 创建者
	@Expose
	@Until(20.0)
	protected Date createDate;	// 创建日期
	protected SysUser updateBy;	// 更新者
	protected Date updateDate;	// 更新日期
	protected String delFlag; 	// 删除标记（0：正常；1：删除；）
	//未绑定数据库字段
	protected boolean sureDel=true; //是否真删除
	protected String ids; 	// 删除是传入的id集合
	protected Date beginDate;		// 开始日期
	protected Date endDate;		// 结束日期
	public DataEntity() {
		super();
		this.delFlag = DeleteStateEnum.NO_DELETE.getVal();
	}
	public DataEntity(String id) {
		super(id);
	}
	/**
	 * 插入之前执行方法，需要手动调用
	 */
	@Override
	public void preInsert(){
		// 不限制ID为UUID，调用setIsNewRecord()使用自定义ID
		if (!this.isNewRecord){
			setId(IdGen.uuid());
		}
		SysUser user = UserUtils.getUser();
		if (StringUtils.isNotBlank(user.getId())){
			this.updateBy = user;
			this.createBy = user;
		}
		//默认未假删
		if(StringUtils.isBlank(delFlag)){
			this.delFlag=DeleteStateEnum.NO_DELETE.getVal();
		}
		this.updateDate = new Date();
		this.createDate = this.updateDate;
	}
	
	/**
	 * 更新之前执行方法，需要手动调用
	 */
	@Override
	public void preUpdate(){
		SysUser user = UserUtils.getUser();
		if (StringUtils.isNotBlank(user.getId())){
			this.updateBy = user;
		}
		this.updateDate = new Date();
	}
	
	@Length(min=0, max=255)
	@Column(name="REMARKS")
	@MyComment("备注")
	public String getRemarks() {
		return remarks;
	}

	public void setRemarks(String remarks) {
		this.remarks = remarks;
	}
	
	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name = "CREATE_USER")
	@MyComment("创建人")
//	@JsonIgnore
//	@JSONField(serialize=false)

//	@NotFound(action= NotFoundAction.IGNORE)//代表可以为空，允许为null
//	hibernate中@ManyToOne默认是立即加载，@OneToMany默认是懒加载
//	但是如果加上了@NotFound之后设置的fetch=FetchType.LAZY是不起作用的，也就是设置@NotFound后变为了立即加载eager

//	FetchType（@OneToOne、@OneToMany等注解里的fetch属性对应的类，本身没有注解）
//	JPA标准的通用加载策略注解属性。FetchType可选值意义与区别如下：
//	FetchType.LAZY：懒加载，在第一次访问关联对象的时候加载
//	FetchType.EAGER：立刻加载，在查询主对象的时候同时加载关联对象。

//	@Fetch
//	hibernate定义了加载关联关系的获取策略。Fetch可选值意义与区别如下：
//	FetchMode.JOIN：始终立刻加载，使用外连(outer join)查询的同时加载关联对象，忽略FetchType.LAZY设定。
//	FetchMode.SELECT：支持懒加载(除非设定关联属性lazy=false)，当访问每一个关联对象时加载该对象，会累计产生N+1条sql语句
//	FetchMode.SUBSELECT：支持懒加载(除非设定关联属性lazy=false)，在访问第一个关联对象时加载所有的关联对象。会累计产生两条sql语句

	@LazyToOne(LazyToOneOption.PROXY)
//	hibernate定义了@ManyToOne 和@OneToOne 关联的延迟选项。LazyToOne可选值意义与区别如下：
//	LazyToOneOption.PROXY：基于代理的延迟加载。
//	LazyToOneOption.NO_PROXY：基于字节码增强的延迟加载 - 注意需要在构建期处理字节码增强。
//	LazyToOneOption.FALSE：非延迟加载的关联。

//	@LazyCollection
//	hibernate定义了@ManyToMany和@OneToMany 关联的延迟选项。LazyCollection可选值意义与区别如下：
//	LazyCollectionOption.TRUE：集合具有延迟性，只有在访问的时候才加载。
//	LazyCollectionOption.EXTRA：集合具有延迟性，并且所有的操作都会尽量避免加载集合， 对于一个巨大的集合特别有用，因为这样的集合中的元素没有必要全部加载。
//	LazyCollectionOption.FALSE：非延迟加载的关联。
	public SysUser getCreateBy() {
		return createBy;
	}

	public void setCreateBy(SysUser createBy) {
		this.createBy = createBy;
	}
	
    @Column(name="CREATE_DATE")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
   	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    /*@Temporal(TemporalType.TIMESTAMP)*/
   	@MyComment("创建时间")
    public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name = "UPDATE_USER")
	@MyComment("修改人")
	@JsonIgnore
	@JSONField(serialize=false)
	public SysUser getUpdateBy() {
		return updateBy;
	}

	public void setUpdateBy(SysUser updateBy) {
		this.updateBy = updateBy;
	}

	@Column(name="UPDATE_DATE")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
   	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    /*@Temporal(TemporalType.TIMESTAMP)*/
   	@MyComment("修改时间")
	public Date getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(Date updateDate) {
		this.updateDate = updateDate;
	}

	@JsonIgnore
	@Length(min=1, max=1)
	@Column(name="DEL_FLAG")
	@MyComment("删除标记")
	public String getDelFlag() {
		return delFlag;
	}

	public void setDelFlag(String delFlag) {
		this.delFlag = delFlag;
	}
	@Transient
	public boolean isSureDel() {
		return sureDel;
	}

	public void setSureDel(boolean sureDel) {
		this.sureDel = sureDel;
	}
	@Transient
	public String getIds() {
		return ids;
	}

	public void setIds(String ids) {
		this.ids = ids;
	}

	@Transient
	public Date getBeginDate() {
		return beginDate;
	}

	public void setBeginDate(Date beginDate) {
		this.beginDate = beginDate;
	}
	@Transient
	public Date getEndDate() {
		return endDate;
	}

	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}

}
